(function() {
	function _createColumn(prop, label, template) {
		if(template) {
			return "<el-table-column prop='" + prop + "' label='" + label + "' show-overflow-tooltip><template scope='scope'>" + template + "</template></el-table-column>";
		} else {
			return "<el-table-column prop='" + prop + "' label='" + label + "' show-overflow-tooltip></el-table-column>";
		}
	}

	function createAllColumn(keys, hasSelection) {
		var tableString = "<el-table ref='table' :data='tableData' :height='height' highlight-current-row @row-click='rowClick' @selection-change='selectionChange'>";
		if(hasSelection) {
			tableString += '<el-table-column type="selection"></el-table-column>';
		}
		for(var i = 0; i < keys.length; i++) {
			tableString += _createColumn(keys[i]["key"], keys[i]["name"], keys[i]["template"]);
		}
		tableString += "</el-table>";
		return tableString;
	}

	/**
	 * 判断一个可滚动元素是否滚动到了底部
	 * e: 元素
	 * fn: 滚动到底部需要执行的回调
	 * isScrollToBottom(div, function(){})
	 */
	function isScrollToBottom(e, fn) {
		// e.srcElement存在兼容性问题，并非标准特性
		// https://developer.mozilla.org/zh-CN/docs/Web/API/Event/target
		// 支持 IE6-8
		var target_ = e.target || e.srcElement,
			// 距离顶部高度
			scrollTop = target_.scrollTop,
			// 滚动区域高度
			scrollHeight = target_.scrollHeight,
			// 文档元素高度
			clientHeight = target_.clientHeight;
		// 文档坐标和视口坐标转换，判断元素滚动到了底部
		if(scrollTop + clientHeight == scrollHeight) {
			if(fn) {
				fn.call();
			}
		}
	}

	/**
	 * 函数节流器，在时间间隔内不触发函数（优化）
	 * 应用场景：需要反复重复执行的事件，如快速重复点击按钮等等
	 * method: 函数 function a(){}
	 * throttle(a)
	 */
	function throttle(method, context) {
		clearTimeout(method.tId);
		method.tId = setTimeout(function() {
			method.call(context);
		}, 100);
	}

	/**
	 * 将源对象合并到目标对象中去——内部方法
	 * src: 源对象
	 * to: 目标对象
	 * return 目标对象
	 * a = {"a": "a"}
	 * b = {"b": "b"}
	 * extend_(a, b) → {a: "a", b: "b"}
	 */
	function extend_(srcObj, toObj) {
		for(var key in srcObj) {
			toObj[key] = srcObj[key];
		}
		return toObj;
	}

	function VanyTable(opts) {
		var el_ = document.getElementById(opts.el.split("#")[1]);
		el_.innerHTML = createAllColumn(opts.keys, opts.selection);
		return table = new Vue({
			el: opts.el,
			data: function() {
				this.opts = opts;
				this.preParams = {};
				return {
					tableData: [],
					params: {
						pageIndex: 1,
						pageSize: 30,
					},
					sels: [],
					height: this.opts.height || 500,
					nodataFlag: false,
				}
			},
			mounted: function() {
				var self = this,
					isScrollToBottom_ = function() {
						if(self.nodataFlag) {
							return false;
						}
						isScrollToBottom(this, self.getData);
					};
				self.$nextTick(function() {
					var tablebody_ = self.$refs["table"].$el.getElementsByClassName("el-table__body-wrapper")[0];
					tablebody_.onscroll = function(e) {
						throttle(isScrollToBottom_, e);
					}
				});
			},
			methods: {
				resetPagination: function() {
					this.tableData = [];
					this.nodataFlag = false;
					this.params.pageIndex = 1;
				},
				getData: function(params, isNewGet) {
					if(isNewGet) {
						this.resetPagination();
					} else {
						if(this.nodataFlag) {
							console.log("已请求完所有数据");
							return false;
						}
					}
					if(params) {
						params = extend_(this.params, params);
						// 保存这一次的请求参数
						this.preParams = {};
						this.preParams = extend_(params, this.preParams);
					} else {
						this.preParams = extend_(this.params, this.preParams);
					}
					VanyAjax(this.opts.url, params || this.preParams, "GET", table.$el).done(function(data) {
						if(data.total === 0) {
							this.nodataFlag = true;
							return;
						}
						if(this.params.pageSize * this.params.pageIndex >= data.total) {
							this.nodataFlag = true;
						}
						var rows = data.rows;
						for(var i = 0; i < rows.length; i++) {
							this.tableData.push(rows[i]);
						}
						this.params.pageIndex++;
					}, false, this);
				},
				rowClick: function(row, event, column) {
					this._rowClick.call(this, this.tableData.indexOf(row), row, event, column);
				},
				selectionChange: function(selection) {
					this.sels = selection;
					this._selectionChange.call(this, selection);
				},
				on: function(type, fn) {
					switch(type) {
						case "rowClick":
							this._rowClick = fn;
							break;
						case "selectionChange":
							this._selectionChange = fn;
							break;
					}
				},
				setHeigth: function(val) {
					this.height = val;
				}
			}
		});
	}
	window.VanyTable = VanyTable;
})();